package com.beiding.render;

import java.util.*;

public class ContentUtils {

    public static boolean isEmpty(Object o) {
        if (o instanceof String) {
            return "".equals(((String) o).trim());
        } else if (o instanceof Collection) {
            return ((Collection) o).size() == 0;
        } else if (o instanceof Map) {
            return ((Map) o).size() == 0;
        } else if (o instanceof Object[]) {
            return ((Object[]) o).length == 0;
        }
        return o == null;
    }

    public static String antToRegex(String ant) {
        return ant.replace("/**", "(/[^/]*)*").replace("*", "[^/]*").replace(".", "\\.");
    }

    private static int minOffset(String[] split, int fromLine) {

        int min = Integer.MAX_VALUE;

        out:
        for (int i = fromLine; i < split.length; i++) {
            String s = split[i];
            //如果是空串,不参与判断
            if (s.trim().equals("")) {
                continue;
            }
            char[] chars = s.toCharArray();
            int k = 0;
            for (char aChar : chars) {
                if (aChar == ' ') {
                    k++;
                } else if (aChar == '\t') {
                    k += 4;
                } else {
                    if (k < min) {
                        min = k;
                    }
                    continue out;
                }
            }
        }

        if (min == Integer.MAX_VALUE) {
            min = 0;
        }

        return min;
    }

    public static String[] splitLines(String text) {

        if (text == null) {
            return null;
        }

        List<String> lines = new ArrayList<>();
        StringBuilder builder = new StringBuilder();

        char[] chars = text.toCharArray();
        for (char c : chars) {
            if (c == '\n') {
                lines.add(builder.toString());
                builder.delete(0, builder.length());
            } else {
                builder.append(c);
            }
        }

        lines.add(builder.toString());

        return lines.toArray(new String[0]);
    }


    public static int indentOfText(String text, String target) {

        int i = text.indexOf(target);
        if (i == -1) {
            return 0;
        }

        char[] chars = text.toCharArray();
        int indent = 0;
        for (int j = i - 1; j > -1; j--) {
            if (chars[j] == '\t') {
                indent += 4;
            } else if (chars[j] == '\n') {
                break;
            } else {
                indent++;
            }
        }
        return indent;
    }

    //fromLine 从哪一行开始进行处理,行从0开始     relative 是否是相对的,如果是相对的,偏移量将加上最小偏移
    public static String indent(String text, int indent, boolean relative, int fromLine) {

        String[] split = splitLines(text);

        if (split.length <= fromLine) {
            return text;
        }

        //最小偏移
        int minOffset = minOffset(split, fromLine);

        if (relative) {
            indent += minOffset;
        }

        StringBuilder builder = new StringBuilder();

        if (minOffset < indent) {//加

            char[] cs = new char[(indent - minOffset)];
            for (int i = 0; i < cs.length; i++) {
                cs[i] = ' ';
            }
            String k = new String(cs);

            String s = split[0];

            if (0 < fromLine || s.trim().equals("")) {//不需要缩进的
                builder.append(s);
            } else {
                builder.append(k).append(s);
            }
            for (int i = 1; i < split.length; i++) {
                s = split[i];
                if (i < fromLine || s.trim().equals("")) {//不需要缩进的
                    builder.append('\n').append(s);
                } else {
                    builder.append('\n').append(k).append(s);
                }
            }

        } else {//裁
            int c = minOffset - indent;
            String s = split[0];
            if (0 < fromLine || s.trim().equals("")) {
                builder.append(s);
            } else {
                builder.append(s.substring(c));
            }
            for (int i = 1; i < split.length; i++) {
                s = split[i];
                if (i < fromLine || s.trim().equals("")) {
                    builder.append('\n').append(s);
                } else {
                    builder.append('\n').append(s.substring(c));
                }
            }
        }

        return builder.toString();

    }


    public static String createId() {
        return "id_" + id++;
    }

    private static int id = 1;

    private static final String random = new Random().nextInt(Integer.MAX_VALUE) + "";

    public static String createHolder() {
        return "<$$$$ ___Holder___" + random + (id++) + " $$$$>";
    }

    //在性能上并没有特别高的要求
    public static StartTagMsg findStart(String s, String tagName, int from) {

        StartTagMsg startTagMsg = new StartTagMsg();

        int startIndex = -1;
        int index;

        //TODO  总是和 start 同在
        int startLen = -1;
        String start;

        //标签名称结束标记
        String[] ends = new String[]{
                " ", "\t", "\n", "\r\n"
        };

        for (String end : ends) {
            start = "<" + tagName + end;
            index = s.indexOf(start, from);
            if (index != -1) {
                if (startIndex == -1) {
                    startIndex = index;
                    startLen = start.length();
                } else if (index < startIndex) {
                    startIndex = index;
                    startLen = start.length();
                }
            }
        }

        start = "<" + tagName + ">";

        index = s.indexOf(start, from);

        //结束返回
        if (index != -1) {
            if (startIndex == -1) {
                startIndex = index;
                startTagMsg.start = startIndex;
                startTagMsg.end = startIndex + start.length();
                startTagMsg.text = s.substring(startTagMsg.start, startTagMsg.end);
                return startTagMsg;
            } else if (index < startIndex) {
                startIndex = index;
                startTagMsg.start = startIndex;
                startTagMsg.end = startIndex + start.length();
                startTagMsg.text = s.substring(startTagMsg.start, startTagMsg.end);
                return startTagMsg;
            }
        }

        start = "<" + tagName + "/>";

        index = s.indexOf(start, from);

        //结束返回
        if (index != -1) {
            if (startIndex == -1) {
                startIndex = index;
                startTagMsg.noBody = true;//无体标签
                startTagMsg.start = startIndex;
                startTagMsg.end = startIndex + start.length();
                startTagMsg.text = s.substring(startTagMsg.start, startTagMsg.end);
                return startTagMsg;
            } else if (index < startIndex) {
                startIndex = index;
                startTagMsg.noBody = true;//无体标签
                startTagMsg.start = startIndex;
                startTagMsg.end = startIndex + start.length();
                startTagMsg.text = s.substring(startTagMsg.start, startTagMsg.end);
                return startTagMsg;
            }

        }


        if (startIndex == -1) {
            return null;
        }

        //TODO 内容开始位置
        int contentStart = startIndex + startLen;

        //  System.out.println(s.charAt(start));

        EndFinder finder = new EndFinder();

        startTagMsg.start = startIndex;
//        startTagMsg.end = end + 1;//TODO 加一个
        startTagMsg.name = tagName;

        try {
            EndFinder.R r = finder.find(s, contentStart);
            if (r == null) {
                return null;
            }

            startTagMsg.attributes = r.attributes;
            if (s.charAt(r.endIndex - 1) == '/') {
                startTagMsg.noBody = true;
            }
            startTagMsg.end = r.endIndex + 1;

        } catch (ErrorExpression e) {
            // e.printStackTrace();
            throw new RuntimeException("错误表达式:" + s);
        }

        startTagMsg.text = s.substring(startTagMsg.start, startTagMsg.end);

        return startTagMsg;
    }

    public static EndTagMsg findEnd(String s, String tagName, int from) {
        String end = "</" + tagName + ">";

        int index = s.indexOf(end, from);

        if (index == -1) {
            return null;
        }

        EndTagMsg endTagMsg = new EndTagMsg();
        endTagMsg.start = index;
        endTagMsg.end = index + end.length();
        endTagMsg.text = s.substring(endTagMsg.start, endTagMsg.end);

        return endTagMsg;
    }

    public static String removeLine(String r, String holder, boolean a) {

        String[] strings = splitLines(r);

        StringBuilder builder = new StringBuilder();

        Iterator<String> iterator = Arrays.asList(strings).iterator();

        if (iterator.hasNext()) {
            String next = iterator.next();
            if (next.contains(holder)) {
                if (!a) {
                    String o = next.replace(holder, "");
                    String to = o.trim();
                    if (!to.equals("")) {
                        builder.append(o);
                    }
                }
            } else {
                builder.append(next);
            }
            while (iterator.hasNext()) {
                next = iterator.next();
                if (next.contains(holder)) {
                    if (!a) {
                        String o = next.replace(holder, "");
                        String to = o.trim();
                        if (!to.equals("")) {
                            builder.append("\n");
                            builder.append(o);
                        }
                    }
                } else {
                    builder.append("\n");
                    builder.append(next);
                }
            }
        }


        return builder.toString();
    }

    /*

        abc
        将被删除的行
        edf

     */
    public static void main(String[] args) {
        String s =
                "        abc\n" +
                        "        将被删除的行 abc\n" +
                        "        edf";

        System.out.println(removeLine(s, "将被删除的行", true));

    }

    private static class ErrorExpression extends RuntimeException {
    }


    //
 /*   public static void main(String[] args) {

        String s = "<block abc/>";

        //寻找开始标签
        StartTagMsg block = findStart(s, "block", 0);
        if (block != null) {
            System.out.println(block.attributes);
            System.out.println(block.noBody);
        }
    }*/

    private static class EndFinder {

        private StringBuilder builder = new StringBuilder();

        private Map<String, String> params = new HashMap<>();

        private String currentParamName;

        private int quotation = 0;

        private Strategy S = new Strategy() {

            @Override
            public String toString() {
                return "字符串";
            }

            @Override
            public boolean h(char c) {


                if (c == ' ' || c == '\t' || c == '\n') {
                    if (quotation == 1) {
                        builder.append(c);
                    }
                } else if (c == '"') {
                    quotation++;
                    if (quotation == 2) {
                        //进行策略转移操作
                        params.put(currentParamName, builder.toString());
                        builder.delete(0, builder.length());
                        strategy = N;
                        quotation = 0;
                        currentParamName = null;
                    }
                } else {
                    if (quotation == 1) {
                        builder.append(c);
                    } else {
                        checkEnd(c);
                        if (end) {
                            end();
                            return true;
                        } else if (ignore) {
                            return false;
                        }
                        throw new ErrorExpression();
                    }
                }

                return false;
            }

            public void end() {
                if (quotation == 2) {//跳出字符串
                    params.put(currentParamName, builder.toString());
                    quotation = 0;
                    currentParamName = null;
                } else {
                    throw new ErrorExpression();
                }
            }
        };

        private Strategy E = new Strategy() {

            @Override
            public String toString() {
                return "等号";
            }

            @Override
            public boolean h(char c) {

                checkEnd(c);

                if (end) {
                    end();
                    return true;
                } else if (ignore) {
                    return false;
                }

                if (c == ' ' || c == '\t' || c == '\n') {
                    //pass
                } else if (c == '"') {
                    throw new ErrorExpression();
                } else if (c == '=') {

                    //切换到字符串处理
                    EndFinder.this.strategy = EndFinder.this.S;
                } else {//按照名称策略继续
                    //未找到等号
                    params.put(currentParamName, null);

                    currentParamName = null;
                    EndFinder.this.strategy = EndFinder.this.N;
                    EndFinder.this.strategy.h(c);

                }

                return false;
            }

            public void end() {

                //TODO 未找到等号
                if (currentParamName != null) {
                    params.put(currentParamName, null);
                }

            }
        };

        //寻找名称
        private Strategy N = new Strategy() {
            @Override
            public String toString() {
                return "名称";
            }

            @Override
            public boolean h(char c) {
                checkEnd(c);
                if (end) {
                    end();
                    return true;
                } else if (ignore) {
                    return false;
                }
                if (c == ' ' || c == '\t' || c == '\n') {
                    if (builder.length() > 0) {//已获取到名称
                        currentParamName = builder.toString();
                        builder.delete(0, builder.length());

                        //切换到等号处理策略
                        EndFinder.this.strategy = E;

                        //重新处理符号
                        EndFinder.this.strategy.h(c);
                    }
                } else if (c == '"') {
                    throw new ErrorExpression();
                } else if (c == '=') {
                    if (builder.length() == 0) {
                        throw new ErrorExpression();
                    } else {
                        currentParamName = builder.toString();
                        builder.delete(0, builder.length());

                        //切换到等号处理策略
                        EndFinder.this.strategy = E;

                        //重新处理符号
                        EndFinder.this.strategy.h(c);
                    }
                } else {
                    builder.append(c);
                }
                return false;
            }

            public void end() {
                if (builder.toString().length() > 0) {
                    params.put(builder.toString(), null);
                }
            }
        };

        private Strategy strategy = N;

        static class R {
            Map<String, String> attributes;
            int endIndex = -1;
        }

        R find(String s, int contentOffset) {
            char[] chars = s.toCharArray();
            for (int i = contentOffset; i < chars.length; i++) {

                //   System.out.println(chars[i] + "  ->  " + strategy);

                //返回值控制是否需要跳出
                if (strategy.h(chars[i])) {
                    R r = new R();
                    r.attributes = params;
                    r.endIndex = i;
                    return r;
                }
            }
            return null;
        }

        private abstract class Strategy {

            boolean[] endHolders = new boolean[2];

            boolean ignore = false;
            boolean end = false;

            abstract boolean h(char c);

            //TODO  结束控制
            void checkEnd(char c) {
                if (c == '/') {
                    endHolders[0] = true;
                    ignore = true;
                } else if (c == '>') {
                    endHolders[1] = true;
                    end = true;
                } else {
                    if (endHolders[0]) {
                        throw new ErrorExpression();
                    }
                }
            }

        }

    }

    /*

            处理效果:去掉

     */
    public static String gap(String text) {

        char[] chars = text.toCharArray();
        int first = 0;

        for (int i = 0; i < chars.length; i++) {

            if (chars[i] == '\n') {
                first = i + 1;
            } else if (chars[i] != ' ' && chars[i] != '\t' && chars[i] != '\r') {
                break;
            }

        }

        int last = text.length();

        for (int i = chars.length - 1; i > -1; i--) {

            if (chars[i] == '\n') {
                last = i;
                if (chars[i - 1] == '\r') {
                    last = i - 1;
                }
            } else if (chars[i] != ' ' && chars[i] != '\t' && chars[i] != '\r') {
                break;
            }

        }
        return text.substring(first, last);

    }

    //格式化结尾
    public static String gapTail(String text, int n) {

        Map<Integer, Integer> is = new HashMap<>();

        char[] chars = text.toCharArray();
        for (int i = chars.length - 1; i > -1; i--) {

            if (chars[i] == '\n') {
                int last = i;
                if (chars[i - 1] == '\r') {
                    last = i - 1;
                }
                is.put(is.size(), last);
            } else if (chars[i] != ' ' && chars[i] != '\t' && chars[i] != '\r') {
                break;
            }

        }

        if (is.size() == 0) {

            return text;
        }

        if (n >= is.size()) {
            int m = n - is.size();
            StringBuilder textBuilder = new StringBuilder(text);
            for (int i = 0; i < m; i++) {
                textBuilder.append('\n');
            }
            return textBuilder.toString();
        }


        int last = is.get(is.size() - n - 1);

        return text.substring(0, last);
    }

    //格式化开头
    public static String gapHead(String text, int n) {

        Map<Integer, Integer> is = new HashMap<>();

        char[] chars = text.toCharArray();

        for (int i = 0; i < chars.length; i++) {
            if (chars[i] == '\n') {
                int first = i + 1;
                is.put(is.size() + 1, first);
            } else if (chars[i] != ' ' && chars[i] != '\t' && chars[i] != '\r') {
                break;
            }

        }

        //TODO 可以补加换行
        if (is.size() == 0) {
            return text;
        }

        if (n >= is.size()) {
            int m = n - is.size();
            StringBuilder textBuilder = new StringBuilder(text);
            for (int i = 0; i < m; i++) {
                textBuilder.insert(0, '\n');
            }
            return textBuilder.toString();
        }

        int first = is.get(is.size() - n);

        return text.substring(first);
    }


    private static class Node {
        private int type;
        private int len;
        private int index;
    }

    private static class Pair {
        private int from;
        private int to;
    }

    public static String removeAnnotation(String text, String pre, String post) {

        if (!text.contains(pre) || !text.contains(post)) {
            return text;
        }

        List<Node> nodes = new ArrayList<>();

        int from = 0;
        while (true) {
            int i = text.indexOf(pre, from);
            if (i == -1) {
                break;
            }

            Node node = new Node();
            node.index = i;
            node.len = pre.length();
            node.type = 0;
            nodes.add(node);
            from = i + node.len + 1;
        }
        from = 0;
        while (true) {
            int i = text.indexOf(post, from);
            if (i == -1) {
                break;
            }

            Node node = new Node();
            node.index = i;
            node.len = post.length();
            node.type = 1;
            nodes.add(node);
            from = i + node.len + 1;
        }

        if (nodes.size() == 0) {
            return text;
        }

        nodes.sort(Comparator.comparingInt(a -> a.index));

        List<Pair> pairs = new ArrayList<>();

        Node start = null;
        for (Node node : nodes) {
            if (node.type == 0) {
                start = node;
            } else {
                if (start != null) {
                    Pair pair = new Pair();
                    pair.from = start.index;
                    pair.to = node.index + node.len;
                    pairs.add(pair);
                    start = null;
                }
            }
        }


        StringBuilder builder = new StringBuilder();

        from = 0;

        Set<String> all = new HashSet<>();

        //TODO 移除空白的注释行
        for (Pair pair : pairs) {
            builder.append(text, from, pair.from);
            String holder = createHolder();
            builder.append(holder);
            all.add(holder);
            from = pair.to;
        }

        builder.append(text.substring(from));

        String s = builder.toString();

        for (String h : all) {
            s = removeLine(s, h, false);
        }

        return s;


    }
/*
    public static void main(String[] args) {

        String s = "   a";

        System.out.println(offset(s, 4));

    }*/

  /*  public static String trim(String text) {

        int first = -1;

        char[] chars = text.toCharArray();

        for (int i = 0; i < chars.length; i++) {
            if (chars[i] == '\n') {
                first=i;
                break;
            } else if (chars[i] != ' ') {
                break;
            }
        }

        return null;
    }*/


    //开始标签信息
    public static class StartTagMsg {
        public Map<String, String> attributes = new HashMap<>();
        public int start = -1;
        public int end = -1;
        public String text;

        //无体标签
        public boolean noBody = false;
        public String name;
    }

    public static class EndTagMsg {
        public int start = -1;
        public int end = -1;
        public String text;
    }

}
